package com.zhouxiaoge.svn.common;

import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author 周明阳
 * @date 2019/7/23 13:05
 */


public class SVNUtil {

    private static final String SVN_USER_NAME = "admin";
    private static final String SVN_PASS_WORD = "admin";
    private static final String SVN_ROOT_URL = "http://localhost:3698/devops/";

    public static SVNRepository getSVNRepository() throws SVNException {
        DAVRepositoryFactory.setup();
        SVNRepositoryFactoryImpl.setup();
        SVNRepository svnRepository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(SVN_ROOT_URL));
        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(SVN_USER_NAME, SVN_PASS_WORD.toCharArray());
        svnRepository.setAuthenticationManager(authManager);
        return svnRepository;
    }

    private static SVNClientManager getSVNClient() {
        //1.通过不同的协议初始化版本库
        DAVRepositoryFactory.setup();
        //2.使用默认选项
        ISVNOptions isvnOptions = SVNWCUtil.createDefaultOptions(true);
        //3.初始化权限
        ISVNAuthenticationManager isvnAuthenticationManager = SVNWCUtil.createDefaultAuthenticationManager(SVN_USER_NAME, SVN_PASS_WORD.toCharArray());
        //4.创建SVNClientManager的实例
        return SVNClientManager.newInstance(isvnOptions, isvnAuthenticationManager);
    }

    /**
     * 在svn上创建目录
     *
     * @param applicationPath svn 目录地址 如：http://localhost:3698/devops/zmy --新建目录 /zmy
     * @param commitMessage   svn日志信息
     * @return svn执行结果
     */
    public static SVNCommitInfo doMkDir(String applicationPath, String commitMessage) {
        try {
            SVNClientManager svnClientManager = getSVNClient();
            SVNURL svnurl = SVNURL.parseURIEncoded(applicationPath);
            return svnClientManager.getCommitClient().doMkDir(new SVNURL[]{svnurl}, commitMessage);
        } catch (SVNException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除svn上指定目录
     *
     * @param applicationPath svn上指定目录
     * @param commitMessage   svn日志信息
     * @return svn执行结果
     */
    public static SVNCommitInfo deleteFiled(String applicationPath, String commitMessage) {
        SVNClientManager svnClient = getSVNClient();
        try {
            SVNURL svnurl = SVNURL.parseURIEncoded(applicationPath);
            SVNURL[] svnUrls = new SVNURL[]{svnurl};
            return svnClient.getCommitClient().doDelete(svnUrls, commitMessage);
        } catch (SVNException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 项目初试导入
     *
     * @param applicationPath      上传到svn的目录（svn） 如：http://localhost:3698/devops/zmy/001/
     * @param localApplicationPath 要上传的项目地址(本地)， 如：D:\ideaworkspace\SpringBoot
     * @param commitMessage        svn日志信息
     * @return svn执行结果
     */
    public static SVNCommitInfo doImport(String applicationPath, String localApplicationPath, String commitMessage) {
        SVNClientManager svnClientManager = getSVNClient();
        SVNProperties svnProperties = new SVNProperties();
        try {
            File file = new File(localApplicationPath);
            SVNURL svnurl = SVNURL.parseURIEncoded(applicationPath);
            return svnClientManager.getCommitClient().doImport(file, svnurl, commitMessage, svnProperties, true, true, SVNDepth.INFINITY);
        } catch (SVNException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 项目检出
     *
     * @param svnPath   项目在svn上的路径 如：http://localhost:3698/devops/zmy/001
     * @param localPath 项目要检出的路径 如：D:\ideaworkspace\zmy
     */
    public static void checkOut(String svnPath, String localPath) {
        try {
            File outPath = new File(localPath);
            SVNClientManager svnClientManager = getSVNClient();
            SVNUpdateClient updateClient = svnClientManager.getUpdateClient();
            updateClient.setIgnoreExternals(false);
            SVNURL svnurl = SVNURL.parseURIEncoded(svnPath);
            long downloadModel = updateClient.doCheckout(svnurl, outPath, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, true);
            System.out.println(downloadModel);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    private static void checkVersionDirectory(File wc) {
        if (!SVNWCUtil.isVersionedDirectory(wc)) {
            try {
                getSVNClient().getWCClient().doAdd(new File[]{wc}, true, false, false, SVNDepth.INFINITY, false, false, true);
            } catch (SVNException e) {
                e.printStackTrace();
            }
        }
        if (wc.isDirectory()) {
            for (File sub : Objects.requireNonNull(wc.listFiles())) {
                if (sub.isDirectory() && sub.getName().equals(".svn")) {
                    continue;
                }
                checkVersionDirectory(sub);
            }
        }
    }

    /**
     * 添加文件到版本库
     *
     * @param localPath 项目路径
     */
    public static void doAdd(String localPath) {
        File file = new File(localPath);
        FileFilter fileFilter = pathname -> !pathname.getName().equalsIgnoreCase(".svn");
        File[] files = file.listFiles(fileFilter);
        //没有版本号的先执行add操作
        List<String> fileList = new ArrayList<>();
        try {
            for (File tempFile : Objects.requireNonNull(files)) {
                SVNClientManager svnClientManager = getSVNClient();
                SVNStatus status = svnClientManager.getStatusClient().doStatus(tempFile, true);
                if (status == null || status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED) {
                    fileList.add(tempFile.getName());
                    svnClientManager.getWCClient().doAdd(tempFile, false, false, false, SVNDepth.INFINITY, false, false);
                }
            }
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    /**
     * 提交文件到svn库
     *
     * @param commitPath    项目路径
     * @param commitMessage svn日志信息
     */
    public static void commit(String commitPath, String commitMessage) {
        try {
            File file = new File(commitPath);
            FileFilter fileFilter = pathname -> !pathname.getName().equalsIgnoreCase(".svn");
            File[] files = file.listFiles(fileFilter);
            SVNClientManager svnClientManager = getSVNClient();
            svnClientManager.getCommitClient().setIgnoreExternals(false);
            SVNProperties svnProperties = new SVNProperties();
            String[] changeLists = new String[]{};
            svnClientManager.getCommitClient().doCommit(files, true, commitMessage, svnProperties, changeLists, false, false, SVNDepth.INFINITY);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    public static void update(String localPath) {
        try {
            File outPath = new File(localPath);
            SVNClientManager svnClient = getSVNClient();
            long l = svnClient.getUpdateClient().doUpdate(outPath, SVNRevision.HEAD, SVNDepth.INFINITY, false, true);
            System.out.println(l);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

//    public static void main(String[] args) {
//        String svnUrl = "http://localhost:3698/devops/zmy/001";
//        doMkDir(svnUrl, "测试新建目录001");
//        deleteFiled(svnUrl, "删除目录001");
//        String applicationLocalPath = "D:\\ideaworkspace\\SpringBoot";
//        doImport(svnUrl, applicationLocalPath, "初始化导入项目");
//        String localPath = "D:\\ideaworkspace\\zmy";
//        checkOut(svnUrl, localPath);
//        String localPath = "D:\\ideaworkspace\\zmy";
//        doAdd(localPath);
//        String commitPath = "D:\\ideaworkspace\\zmy";
//        commit(commitPath, "提交");
////        String localPath = "D:\\ideaworkspace\\zmy";
//        update(localPath);
//    }
}
